package service

import (
	"awesomeProject/app/model"
	"awesomeProject/app/request"
	"awesomeProject/app/response"
	"awesomeProject/global"
	"awesomeProject/util"
	"context"
	"github.com/shopspring/decimal"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"strings"
	"time"
)

type ShopFlowSourceSrv struct{}

func (s *ShopFlowSourceSrv) ShopFlowSource(req request.ShopFlowSource) response.Resp {
	filter := bson.D{{"shop_id", req.ShopId}}
	preFilter := bson.D{{"shop_id", req.ShopId}}
	if req.DateVal != "" {
		if req.DateType == 1 || req.DateType == 4 { // 日期
			filterDate, _ := time.Parse("2006-01-02", req.DateVal)
			filter = append(filter, bson.E{Key: "date", Value: filterDate})

			preDate := filterDate.AddDate(0, 0, -1)
			preFilter = append(preFilter, bson.E{Key: "date", Value: preDate})
		} else if req.DateType == 2 || req.DateType == 3 { // 近7天or近30天
			dateRange := strings.Split(req.DateVal, "~")
			sDate, _ := time.Parse("2006-01-02", dateRange[0])
			eDate, _ := time.Parse("2006-01-02", dateRange[1])
			filter = append(filter, bson.E{Key: "date", Value: bson.M{"$gte": sDate, "$lte": eDate}})

			subDays := -7
			if req.DateType == 3 {
				subDays = -30
			}
			preSDate := sDate.AddDate(0, 0, subDays)
			preEDate := eDate.AddDate(0, 0, subDays)
			preFilter = append(preFilter, bson.E{Key: "date", Value: bson.M{"$gte": preSDate, "$lte": preEDate}})
		} else if req.DateType == 5 { // 月份
			month, _ := time.Parse("2006-01", req.DateVal)
			sd := util.GetMonthStartAndEnd(month.Year(), int(month.Month()))
			filter = append(filter, bson.E{Key: "date", Value: bson.M{"$gte": sd["start"], "$lte": sd["end"]}})

			preMonth := month.AddDate(0, -1, 0)
			preSd := util.GetMonthStartAndEnd(preMonth.Year(), int(month.Month()))
			filter = append(filter, bson.E{Key: "date", Value: bson.M{"$gte": preSd["start"], "$lte": preSd["end"]}})
		}
	}

	match := bson.D{{"$match", filter}}
	preMatch := bson.D{{"$match", preFilter}}
	group := bson.D{{
		"$group", bson.D{
			{"_id", bson.D{{"shop_id", bson.M{"$toInt": "$shop_id"}}, {"source_id", bson.M{"$toInt": "$sourceId"}}}},
			{"parent_source_id", bson.M{"$last": "$parentSourceId"}},
			{"ctm_item_click_uv", bson.M{"$sum": bson.M{"$toInt": "$indicate.ctm_item_click_uv.content"}}},
			{"item_cart_uv", bson.M{"$sum": bson.M{"$toInt": "$indicate.item_cart_uv.content"}}},
			{"order_uv", bson.M{"$sum": bson.M{"$toInt": "$indicate.order_uv.content"}}},
			//{"ctm_order_view_rate", bson.M{"$sum": bson.M{"$toDouble": bson.M{"$replaceAll": bson.M{ "input": "$ctm_order_view_rate", "find": "%", "replacement": "" }}}}},
		},
	}}
	lookup := bson.D{{
		"$lookup", bson.M{
			"from":         "traffic_meta",
			"localField":   "_id.source_id",
			"foreignField": "sourceId",
			"as":           "source",
		},
	}}
	unwind := bson.D{{"$unwind", "$source"}}
	sort := bson.D{{"$sort", bson.D{{"parent_source_id", 1}}}}
	cursor, err := global.MongoDB.Collection("shop_flow_source").Aggregate(context.TODO(), mongo.Pipeline{match, group, lookup, sort, unwind})
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	var result []model.ShopFlowSource
	if err = cursor.All(context.TODO(), &result); err != nil {
		return response.ErrQuery
	}
	if len(result) == 0 {
		return response.OK
	}
	preCursor, err := global.MongoDB.Collection("shop_flow_source").Aggregate(context.TODO(), mongo.Pipeline{preMatch, group, lookup, sort, unwind})
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	var preResult []model.ShopFlowSource
	if err = preCursor.All(context.TODO(), &preResult); err != nil {
		return response.ErrQuery
	}

	preFormat := map[uint]model.ShopFlowSource{}
	for _, val := range preResult {
		preFormat[val.ID["source_id"]] = val
	}
	// 计算逻辑
	for i, val := range result {
		val.SourceId = val.ID["source_id"]
		sourceId := val.ID["source_id"]
		if _, ok := preFormat[sourceId]; ok {
			preVal := preFormat[sourceId]
			val.OrderUvCompare = util.IncreasePercent(
				decimal.NewFromInt(int64(preVal.OrderUv)),
				decimal.NewFromInt(int64(val.OrderUv)),
			)
			val.CtmItemClickUvCompare = util.IncreasePercent(
				decimal.NewFromInt(int64(preVal.CtmItemClickUv)),
				decimal.NewFromInt(int64(val.CtmItemClickUv)),
			)
			val.ItemCartUvCompare = util.IncreasePercent(
				decimal.NewFromInt(int64(preVal.ItemCartUv)),
				decimal.NewFromInt(int64(val.ItemCartUv)),
			)
			val.CtmOrderViewRate = util.RatePercent(
				decimal.NewFromInt(int64(val.OrderUv)),
				decimal.NewFromInt(int64(val.CtmItemClickUv)),
			)
			preVal.CtmOrderViewRate = util.RatePercent(
				decimal.NewFromInt(int64(preVal.OrderUv)),
				decimal.NewFromInt(int64(preVal.CtmItemClickUv)),
			)
			val.CtmOrderViewRateCompare = util.IncreasePercent(preVal.CtmOrderViewRate, val.CtmOrderViewRate)
		} else {
			if val.OrderUv > 0 {
				val.OrderUvCompare = decimal.NewFromInt(1)
			} else {
				val.OrderUvCompare = decimal.NewFromInt(0)
			}
			if val.CtmItemClickUv > 0 {
				val.CtmItemClickUvCompare = decimal.NewFromInt(1)
			} else {
				val.CtmItemClickUvCompare = decimal.NewFromInt(0)
			}
			if val.ItemCartUv > 0 {
				val.ItemCartUvCompare = decimal.NewFromInt(1)
			} else {
				val.ItemCartUvCompare = decimal.NewFromInt(0)
			}
		}
		result[i] = val
	}
	return response.OK.WithData(s.genTree(result, 0))
}

func (s *ShopFlowSourceSrv) genTree(beGen []model.ShopFlowSource, parent uint) []model.ShopFlowSource {
	var formatBeGen []model.ShopFlowSource
	for _, item := range beGen {
		pid := item.ParentSourceId
		sourceId := item.ID["source_id"]
		if pid == parent {
			hasChildren := false
			for _, it := range beGen {
				if it.ParentSourceId == sourceId {
					hasChildren = true
					break
				}
			}

			if hasChildren {
				item.Children = s.genTree(beGen, sourceId)
			}
			formatBeGen = append(formatBeGen, item)

		}
	}

	return formatBeGen
}
